#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <ctime>
#include <fstream>
#include <atomic>
#include <boost/algorithm/string.hpp> //boost库
using namespace std;

// 公共的工具包
namespace ns_util
{
    // test_1:构建一个完整路径文件的工具包

    static const string PrefixName = "./temp/";

    class path_util
    {
        static string AddPrefixSuffix(const string &file_name, const string &suffix)
        {
            string path_name = PrefixName + file_name + suffix;
            return path_name;
        }

        // file_name->./temp/file_name.cpp
        // file_name->./temp/file_name.ece
        // file_name->./temp/file_name.err

    public: // 1.编译时的临时文件
        // .1源文件
        static string Src(const string &file_name)
        {
            return AddPrefixSuffix(file_name, ".cpp");
        }

        // .2目标文件
        static string Exe(const string &file_name)
        {
            return AddPrefixSuffix(file_name, ".exe");
        }

        // .3错误文件
        static string Compile_err(const string &file_name)
        {
            return AddPrefixSuffix(file_name, ".compile_err");
        }

    public: // 2.运行时的临时文件
        // .1标准输入: 不考虑用户自测, 使用给定用例进行测试
        static string Stdin(const string &file_name)
        {
            return AddPrefixSuffix(file_name, ".stdin");
        }

        // .2标准输出: 程序运行完成的输出结果
        static string Stdout(const string &file_name)
        {
            return AddPrefixSuffix(file_name, ".stdout");
        }

        // .3标准错误: 程序运行出错结果
        static string Stderr(const string &file_name)
        {
            return AddPrefixSuffix(file_name, ".stderr");
        }
    };

    // test_2:构建一个时间获取的工具包
    class time_util
    {
    public:
        // 获得当前时间
        static string GetCurTime()
        {
            // 获取时间戳
            std::time_t currentTime = std::time(nullptr);

            // 时间戳转换
            std::tm *localTime = std::localtime(&currentTime);
            char buffer[80];
            std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", localTime);
            return buffer;
        }

        // 获得毫秒级时间戳（用于生成唯一文件名）
        static string GetMSTime()
        {
            struct timeval curtime;
            gettimeofday(&curtime, nullptr); // 获取当前时间戳
            return to_string(curtime.tv_sec * 1000 + curtime.tv_usec / 10000);
        }
    };

    // test_3:构建一个文件相关信息的工具包
    class file_util
    {
    public:
        // 判断文件内部是否有数据
        static bool FileIsData(const string &filename)
        {
            struct stat st;
            stat(filename.c_str(), &st);
            if (st.st_size == 0)
            {
                return false;
            }
            return true;
        }

        // 判断文件是否存在
        static bool FileExit(const string &filename)
        {
            struct stat st;
            // stat查看文件状态的函数，状态结果写入到st中
            int ret = stat(filename.c_str(), &st);
            if (ret == 0)
            {
                return true;
            }
            return false;
        }

        // 生成唯一文件名(通过毫秒级时间戳+原子性递增整数)
        static string UniqueFileName()
        {
            // 原子性是为了防止多线程同时调用
            static atomic<int> counter(0); // 防止每次调用都重新创建对象
            counter++;
            return time_util::GetMSTime() + "_" + to_string(counter);
        }

        // 将代码写入文件中
        static bool WriteFile(const string &file_name, const string &code)
        {
            // int fd = open(file_name.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
            // write(fd, code.c_str(), code.size());
            // close(fd);

            ofstream out(file_name);
            if (!out.is_open())
            {
                return false;
            }
            out.write(code.c_str(), code.size());
            out.close(); // 关闭文件描述符

            return true;
        }

        // 读取文件内容
        static string ReadFile(const string &file_name)
        {
            // char buffer[1024];
            // int fd = open(file_name.c_str(), O_RDONLY);
            // int n = read(fd, buffer, sizeof(buffer));
            // if (n > 0)
            // {
            //     buffer[n] = 0;
            // }
            // close(fd);
            // return buffer;

            char buffer[1024];
            ifstream in(file_name);

            // in.read(buffer, sizeof(buffer));//有内存大小设置
            string ret, line;
            while (getline(in, line)) // 不会读取\n
            {
                ret += line;
                ret += '\n';
            }
            in.close(); // 关闭文件描述符

            return ret;
        }
    };

    // test_4:构建一个字符串相关操作的工具包
    class str_util
    {
    public:
        // 字符串分割
        bool static SplitStr(const string &line, vector<string> *out, const string &sep)
        {
            // 1.使用stl库中的string进行切割
            //  int begin = 0;
            //  while (true)
            //  {
            //      int end = line.find(sep, begin);
            //      if (end = string::npos)
            //          break;
            //      out->push_back(line.substr(begin, end - begin));
            //      begin = end + sep.size();
            //  }

            // 2.使用boost库
            // 参数一的形参是引用接收，参数四是针对多个重复分隔符是否保留的问题
            boost::split(*out, line, boost::is_any_of(sep),
                         boost::algorithm::token_compress_on);
            return true;
        }
    };
};